package com.booksystem.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.booksystem.common.RestResult;
import com.booksystem.dto.*;
import com.booksystem.dto.AddToCartDTO;
import com.booksystem.dto.CartUpdateQuantityDTO;
import com.booksystem.dto.CheckoutCartDTO;
import com.booksystem.dto.GetCartListDTO;
import com.booksystem.entity.ProductInfo;
import com.booksystem.entity.ShoppingCartDO;
import com.booksystem.entity.UserDO;
import com.booksystem.exception.BusinessException;
import com.booksystem.mapper.ProductMapper;
import com.booksystem.mapper.ShoppingCartMapper;
import com.booksystem.mapper.UserMapper;
import com.booksystem.service.ShoppingCartService;
import com.booksystem.utils.OrderNoGenerator;
import java.math.BigDecimal;
import java.util.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * <p>
 *   购物车业务逻辑实现类
 * </p>
 * @author 段伟豪
 */
@Slf4j
@Service
public class ShoppingCartServiceImpl implements ShoppingCartService {

    @Autowired
    private ShoppingCartMapper shoppingCartMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private OrderNoGenerator orderNoGenerator;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RestResult<Boolean> addToCart(AddToCartDTO addToCartDTO) {
        // 校验用户是否存在
        QueryWrapper<UserDO> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.select("user_id").eq("user_id", addToCartDTO.getUserId());
        UserDO userInfo = userMapper.selectOne(userQueryWrapper);
        if (userInfo == null) {
            return new RestResult<>("000001", "用户不存在");
        }

        // 校验商品是否存在且上架
        QueryWrapper<ProductInfo> productQueryWrapper = new QueryWrapper<>();
        productQueryWrapper.select("product_id", "stock_quantity", "is_on_sale")
                .eq("product_id", addToCartDTO.getProductId())
                .eq("is_on_sale", 1);
        ProductInfo productInfo = productMapper.selectOne(productQueryWrapper);
        if (productInfo == null) {
            return new RestResult<>("000001", "商品不存在或未上架");
        }

        // 判断商品库存是否充足
        if (addToCartDTO.getQuantity() > productInfo.getStockQuantity()) {
            return new RestResult<>("000001", "商品库存不足");
        }

        // 检查购物车内是否已存在该商品
        ShoppingCartDO existingItem = shoppingCartMapper.selectByUserIdAndProductId(
                addToCartDTO.getUserId(), addToCartDTO.getProductId());

        if (existingItem != null) {
            // 若已存在则增加商品数量
            existingItem.setQuantity(existingItem.getQuantity() + addToCartDTO.getQuantity());
            boolean updated = shoppingCartMapper.updateById(existingItem) > 0;
            if (!updated) {
                throw new BusinessException("000001", "更新购物车失败");
            }
        } else {
            // 若不存在则新增购物车记录
            ShoppingCartDO newItem = new ShoppingCartDO();
            newItem.setUserId(addToCartDTO.getUserId());
            newItem.setProductId(addToCartDTO.getProductId());
            newItem.setQuantity(addToCartDTO.getQuantity());
            newItem.setSelected(1); // 默认选中
            newItem.setCreateBy("system");
            newItem.setUpdateBy("system");

            boolean inserted = shoppingCartMapper.insert(newItem) > 0;
            if (!inserted) {
                throw new BusinessException("000001", "添加购物车失败");
            }
        }

        return new RestResult<>("000000", "调用成功", true);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RestResult<Boolean> updateCartQuantity(CartUpdateQuantityDTO cartUpdateQuantityDTO) {
        // 校验购物车记录是否存在
        ShoppingCartDO cartItem = shoppingCartMapper.selectById(cartUpdateQuantityDTO.getCartId());
        if (cartItem == null) {
            return new RestResult<>("000001", "购物车记录不存在");
        }

        // 校验商品库存是否充足
        QueryWrapper<ProductInfo> productQueryWrapper = new QueryWrapper<>();
        productQueryWrapper.select("stock_quantity")
                .eq("product_id", cartItem.getProductId())
                .eq("is_on_sale", 1);
        ProductInfo productInfo = productMapper.selectOne(productQueryWrapper);
        if (productInfo == null || cartUpdateQuantityDTO.getQuantity() > productInfo.getStockQuantity()) {
            return new RestResult<>("000001", "商品库存不足");
        }

        // 更新购物车商品数量
        cartItem.setQuantity(cartUpdateQuantityDTO.getQuantity());
        cartItem.setUpdateBy("system");

        boolean updated = shoppingCartMapper.updateById(cartItem) > 0;
        if (!updated) {
            throw new BusinessException("000001", "更新购物车失败");
        }

        return new RestResult<>("000000", "调用成功", true);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RestResult<Boolean> deleteCartItem(Long cartId) {
        // 校验购物车记录是否存在
        ShoppingCartDO cartItem = shoppingCartMapper.selectById(cartId);
        if (cartItem == null) {
            return new RestResult<>("000001", "购物车记录不存在");
        }

        // 删除指定购物车记录
        boolean deleted = shoppingCartMapper.deleteById(cartId) > 0;
        if (!deleted) {
            throw new BusinessException("000001", "删除购物车失败");
        }

        return new RestResult<>("000000", "调用成功", true);
    }

    @Override
    public RestResult<List<ShoppingCartDO>> getCartList(GetCartListDTO getCartListDTO) {
        // 校验用户是否存在
        QueryWrapper<UserDO> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.select("user_id").eq("user_id", getCartListDTO.getUserId());
        UserDO userInfo = userMapper.selectOne(userQueryWrapper);
        if (userInfo == null) {
            return new RestResult<>("000001", "用户不存在");
        }

        // 查询当前用户的购物车信息
        List<ShoppingCartDO> cartItems = shoppingCartMapper.selectListByUserId(getCartListDTO.getUserId());
        return new RestResult<>("000000", "调用成功", cartItems);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RestResult<Boolean> checkoutCart(CheckoutCartDTO checkoutCartDTO) {
        // 校验用户是否存在
        QueryWrapper<UserDO> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.select("user_id").eq("user_id", checkoutCartDTO.getUserId());
        UserDO userInfo = userMapper.selectOne(userQueryWrapper);
        if (userInfo == null) {
            return new RestResult<>("000001", "用户不存在");
        }

        // 验证所选购物车项是否存在
        QueryWrapper<ShoppingCartDO> cartQueryWrapper = new QueryWrapper<>();
        cartQueryWrapper.in("cart_id", checkoutCartDTO.getSelectedCartIds());
        List<ShoppingCartDO> cartItems = shoppingCartMapper.selectList(cartQueryWrapper);
        if (cartItems.size() != checkoutCartDTO.getSelectedCartIds().size()) {
            return new RestResult<>("000001", "购物车项不存在");
        }

        // 生成订单编号
        String orderNo = orderNoGenerator.generateOrderNo();

        // 计算总金额
        BigDecimal totalAmount = calculateTotalAmount(cartItems);

        // 创建订单主表记录（此处省略具体插入逻辑）
        // 实际项目中应包含订单主表的创建及保存操作

        // 批量插入订单明细（此处省略具体插入逻辑）
        // 实际项目中应包含订单明细的批量插入操作

        // 扣除对应商品库存（此处省略具体扣减逻辑）
        // 实际项目中应遍历购物车项并更新商品库存

        // 清空已结算的购物车项
        shoppingCartMapper.deleteBatchIds(checkoutCartDTO.getSelectedCartIds());

        return new RestResult<>("000000", "调用成功", true);
    }

    /**
     * 计算购物车项总金额
     *
     * @param cartItems 购物车项列表
     * @return 总金额
     */
    private BigDecimal calculateTotalAmount(List<ShoppingCartDO> cartItems) {
        BigDecimal totalAmount = BigDecimal.ZERO;
        for (ShoppingCartDO item : cartItems) {
            // 这里应该从数据库获取实际的商品单价来计算小计
            // 示例假设每个商品单价为固定值，实际情况需要根据商品ID获取价格
            BigDecimal unitPrice = BigDecimal.valueOf(99.99); // 假设单价为99.99元
            BigDecimal subtotal = unitPrice.multiply(BigDecimal.valueOf(item.getQuantity()));
            totalAmount = totalAmount.add(subtotal);
        }
        return totalAmount;
    }
}